package com.zh.freechat;

import com.zh.freechat.domain.message.repository.ChatGroupRepository;
import com.zh.freechat.domain.user.entity.GroupRelId;
import com.zh.freechat.domain.user.entity.UserRelId;
import com.zh.freechat.domain.user.repository.real.UserRelationFriendMapper;
import com.zh.freechat.openfegin.ChatServiceStarter;
import com.zh.freechat.openfegin.grpc.ChatServiceProvider;
import com.zh.mycommon.util.Fnv32aHash;
import com.zh.mycommon.value.Tuple2;
import com.zh.mycommon.value.Tuple3;
import com.zh.webcommon.EnableMybatisAudit;
import com.zh.webcommon.common.support.SpringContextHolder;
import com.zh.webcommon.upload.EnableMinioClient;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.zh.freechat.common.CacheKeysConst.REDIS_KEY_ChatGroup_Hash;
import static com.zh.freechat.common.CacheKeysConst.REDIS_KEY_ChatRelId_Hash;

/**
 * @author ZH
 * @date 9:54 2021/5/9
 */
@Slf4j
@MapperScan({"com.zh.freechat"})
@EnableMybatisAudit
@EnableMinioClient
@EnableScheduling
@SpringBootApplication
public class App implements CommandLineRunner {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
        System.err.printf("application startup success... [server.port=%s, spring.profiles.active=%s]%n", SpringContextHolder.getProperty("server.port"), SpringContextHolder.getProperty("spring.profiles.active"));
    }

    @Override
    public void run(String... args) throws Exception {
        //启动gRPC服务
        ChatServiceProvider chatServiceProvider = SpringContextHolder.getBean(ChatServiceProvider.class);
        new ChatServiceStarter().start(9989, chatServiceProvider);

        //redis 缓存加载
        StringRedisTemplate redisTemplate = SpringContextHolder.getBean(StringRedisTemplate.class);

        UserRelationFriendMapper friendRelRepository = SpringContextHolder.getBean(UserRelationFriendMapper.class);
        List<UserRelId> allRel = friendRelRepository.findRelIdAll();

        Map<Integer, Map<String, String>> mapMap = allRel.stream()
                .map(e -> {
                    var tuple = relKey(e.getUser1(), e.getUser2());
                    return new Tuple3<>(tuple.v2(), tuple.v1(), e.getId().toString()); // index, key, value
                })
                .collect(Collectors.groupingBy(Tuple3::v1, Collectors.toMap(Tuple3::v2, Tuple3::v3)));


        mapMap.forEach((index, kv) -> {
            redisTemplate.opsForHash().putAll(REDIS_KEY_ChatRelId_Hash + index, kv);
        });


        ChatGroupRepository groupRelRepository = SpringContextHolder.getBean(ChatGroupRepository.class);

        List<GroupRelId> allGroupRel = groupRelRepository.findRelIdAll();

        Map<Integer, Map<String, String>> groupMap = allGroupRel.stream()
                .map(e -> {
                    var index = e.getId() % 16;
                    return new Tuple3<>((int) index, e.getId().toString(), e.getUserIds()); // index, key, value
                })
                .collect(Collectors.groupingBy(Tuple3::v1, Collectors.toMap(Tuple3::v2, Tuple3::v3)));

        groupMap.forEach((index, kv) -> {
            redisTemplate.opsForHash().putAll(REDIS_KEY_ChatGroup_Hash + index, kv);
        });
    }

    static Tuple2<String, Integer> relKey(String user1, String user2) {
        String key;
        if (user1.compareTo(user2) < 0) {
            key = user1 + "+" + user2;
        } else {
            key = user2 + "+" + user1;
        }
        return new Tuple2<>(key, (int) (Fnv32aHash.hash(key) % 16));
    }
}
